import cv2
import numpy as np
import os
import matplotlib.pyplot as plt

# 读取图像文件
image = cv2.imread(r'hanzi1.jpg')

# 将图像转换为灰度图
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 利用全局阈值处理（Otsu方法自动计算最佳阈值）二值化图像
_, binary_image1 = cv2.threshold(image_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
binary_image = cv2.bitwise_not(binary_image1)

# 创建元素结构
kernel = np.ones((3, 3), np.uint8)

# 进行腐蚀操作，迭代3次增强腐蚀效果
eroded_img = cv2.erode(binary_image, kernel, iterations=3)

# 对图像进行膨胀操作
dilated_img = cv2.dilate(eroded_img, kernel, iterations=2)

# 定义中值滤波器的核大小
kernel_size = 7

# 应用中值滤波去除dilated_img中的小白点
median_filtered_img = cv2.medianBlur(dilated_img, kernel_size)

# 定义结构元素（这里使用一个大的椭圆形结构元素）
kernel2 = np.ones((15, 15), np.uint8)

# 执行闭运算
closed_img = cv2.morphologyEx(median_filtered_img, cv2.MORPH_CLOSE, kernel2,iterations=4)

#先利用高斯滤波对closed_image去噪，再使用Canny进行边缘检测
img_blur = cv2.GaussianBlur(closed_img, (3, 3), 0)
edges = cv2.Canny(img_blur, threshold1=50, threshold2=200)

# 提取轮廓
contours, _ = cv2.findContours(
    edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 创建字符图像保存目录
chars_dir = 'chars'
if not os.path.exists(chars_dir):
    os.makedirs(chars_dir)

count = 1
for contour in contours:
    # 计算轮廓周长
    perimeter = cv2.arcLength(contour, True)
    print("轮廓周长：", perimeter)

    if 309 < perimeter < 1400 :
        # 获取轮廓的边界矩形
        x, y, w, h = cv2.boundingRect(contour)

        # 在原图上画出矩形
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 5)

        # 提取并保存字符图像
        char_img = image_gray[y:y + h, x:x + w]
        char_filename = os.path.join(chars_dir, f'{count}.png')
        cv2.imwrite(char_filename, char_img)
        count += 1





# 创建画布
fig, axs = plt.subplots(2, 4, figsize=(15, 10))

# 在画布上显示图像

axs[0, 0].imshow(image_gray, cmap='gray')
axs[0, 0].set_title('L_grayscale')

axs[0, 1].imshow(binary_image, cmap='gray')
axs[0, 1].set_title('L_ary')

axs[0, 2].imshow(eroded_img, cmap='gray')
axs[0, 2].set_title('L_ered')

axs[0, 3].imshow(median_filtered_img, cmap='gray')
axs[0, 3].set_title('L_mian')

axs[1, 0].imshow(closed_img, cmap='gray')
axs[1, 0].set_title('L_cled')

axs[1, 1].imshow(edges, cmap='gray')
axs[1, 1].set_title('L_es')

axs[1, 2].imshow(image, cmap='gray')
axs[1, 2].set_title('boox')
# 隐藏坐标轴
for ax in axs.flat:
    ax.axis('off')


# 调整子图之间的间距
plt.subplots_adjust(wspace=0.1, hspace=0.1)

#显示画布
plt.show()